import { Injectable,Inject } from '@angular/core';
import {HttpClient,HttpHeaders} from "@angular/common/http";
import {Task} from "../domain"
import {Observable,from,pipe,of} from "rxjs";
import {map,mergeMap,count,switchMap,mapTo,concat,reduce} from "rxjs/operators";
import {TaskList} from "src/app/domain/task-list.model";

@Injectable({
  providedIn: 'root'
})
export class TaskService {

  private readonly domain = 'tasks';
  private headers = new HttpHeaders({
    'content-Type':'application/json'
  })
  constructor(private http:HttpClient,@Inject('BASE_CONFIG') private config) { }
  //post
  add(task:Task):Observable<Task>{
    task.id = null;
    const uri = `${this.config.uri}/${this.domain}`;
    return this.http.post(uri,JSON.stringify(task),{headers:this.headers}).pipe(
      map(res=>res as Task)
    )
  }
  //post
  update(task:Task): Observable <Task>{
    const uri = `${this.config.uri}/${this.domain}/${task.id}`;
    const toUpdate = {
      desc:task.desc,
      priority:task.priority,
      dueDate:task.dueDate,
      reminder:task.reminder,
      ownerId:task.ownerId,
      participantIds:task.participantIds,
      remark:task.remark
    };
    return this.http.patch(uri,JSON.stringify(toUpdate),{headers:this.headers}).pipe(
      map(res => res as Task)
    )
  }
  //delete
  del(task:Task):Observable<Task>{
    const uri = `${this.config.uri}/taskLists/${task.id}`;
    return this.http.delete(uri).pipe(
      mapTo(task)
    );
  }
  //get
  getTasks(taskListId:string):Observable<Task[]>{
    const uri = `${this.config.uri}/${this.domain}`;
    return this.http.get(uri,{params:{'taskListId':taskListId}}).pipe(
      map(res=>res as Task[])
    )
  }
  getByLists(lists:TaskList[]){
   return from(lists).pipe(
      map(list=>list),
      mergeMap(list=>this.getTasks(list['id'])),
      reduce((tasks:Task[],t:Task[])=>[...tasks,...t],[])
    )
  }
  complete(task:Task):Observable<Task>{
    const uri = `${this.config.uri}/${this.domain}/${task.id}`;
    return this.http
      .patch(uri,JSON.stringify({completed:!task.completed}),{headers:this.headers}).pipe(
        map(res => res as Task)
      );
  }
  move(taskId:string,taskListId:string):Observable<Task>{
    const uri = `${this.config.uri}/${this.domain}/${taskId}`;
    return this.http
      .patch(uri,JSON.stringify({taskListId:taskListId}),{headers:this.headers}).pipe(
        map(res =>res as Task)
      );
  }
  moveAll(srcListId:string,targetListId:string):Observable<Task[]>{
    return this.getTasks(srcListId).pipe(
      mergeMap((tasks: Task[])=>from(tasks)),
      mergeMap((task: Task)=>this.move(task['id'], targetListId)),
      reduce((arr:Task[],x:Task)=>[...arr,x],[]),
    );
  }
  getUserTasks(userId: string): Observable<Task[]> {
    const uri = `${this.config.uri}/${this.domain}`;
    return this.http.get(uri, {params: {'ownerId': userId}}).pipe(
      map(res => res as Task[])
    );
  }
}
